<?php
namespace app\admin\controller;

class Excel extends Common
{
    /**
     * 引入excel组件 并初始化
     */
    protected static function init()
    {
        import('PHPExcel.Classes.PHPExcel');
        import('PHPExcel.Classes.PHPExcel.IOFactory.PHPExcel_IOFactory');
        import('PHPExcel.Classes.PHPExcel.Reader.Excel5');

        ini_set('memory_limit', '512M');          // 设置内存使用率
    }

    /**
     * 获取excel的数据
     * @param  string $input_name input框（type='file'）name值
     * @param  bool   $create     不存在路径是否创建路径
     * @return array
     */
    public static function getExcelDate($input_name)
    {
        // 初始化
        self::init();

        // 获取表单上传文件
        $file = request()->file($input_name);
        if (!$file) {
            return retArray('', 211, '无文件');
        }

        // 上传验证后缀名,以及上传之后移动的地址
        $info = $file->validate(['ext' => 'xlsx'])->check();
        if (!$info) {
            return retArray('', 212, $file->getError());
        }

        $info = $file->getInfo();

        $reader   = \PHPExcel_IOFactory::createReader('Excel2007');        // 设置以Excel5格式(Excel97-2003工作簿)
        $reader->setReadDataOnly(true);                                    // 只读数据
        $PHPExcel = $reader->load($info['tmp_name'], $encode = 'utf-8');   // 载入excel文件
        $sheet    = $PHPExcel->getSheet(0);                                // 读取第一個工作表
        // $highestRow    = $sheet->getHighestRow();                       // 取得总行数
        // $highestColumm = $sheet->getHighestColumn();                    // 取得总列数
        $excel_array  = $sheet->toArray();                                 // 转换为数组格式

        return retArray($excel_array, 200, '读取成功');
    }

    /**
     * 导出excel文件
     * @param array  $title     大标题
     * @param array  $header    标题数组
     * @param array  $data      用于遍历的二维数组
     * @param string $filename  文件名
     * @param int    $length    单元格宽度
     */
    public static function getExcelFile($title = null, $header = [], $data = [], $filename = '', $length = 25)
    {
        // 初始化

        self::init();

        header("Content-Type:text/html;charset=utf-8");
        if (empty($data)) {
            die("无数据可导出");
        }
        if (!is_array($data)) {
            die('数据结构错误');
        }
        //检查文件名
        if (empty($filename)) {
            $filename = date('Y-m-d', time());
        }

        $cacheMethod   = \PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
        $cacheSettings = array('memoryCacheSize' => '128MB');
        \PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);

        $objPHPExcel = new \PHPExcel();

        // 设置文件的一些属性，在xls文件——>属性——>详细信息里可以看到这些值，xml表格里是没有这些值的
        $objPHPExcel->getProperties()                                                                       // 获得文件属性对象，给下文提供设置资源
        ->setCreator("Maarten Balliauw")                                                        // 设置文件的创建者
        ->setLastModifiedBy("Maarten Balliauw")                                                 // 设置最后修改者
        ->setTitle("Office 2007 XLSX Test Document")                                            // 设置标题
        ->setSubject("Office 2007 XLSX Test Document")                                          // 设置主题
        ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")    // 设置备注
        ->setKeywords("office 2007 openxml php")                                                // 设置标记
        ->setCategory("Test result file");                                                      // 设置类别
        // 横向单元格标识
        $cellName = array(
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ',
            'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BK', 'BL', 'BM', 'BN', 'BO', 'BP', 'BQ', 'BR', 'BS', 'BT', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ',
            'CA', 'CB', 'CC', 'CD', 'CE', 'CF', 'CG', 'CH', 'CI', 'CJ', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CQ', 'CR', 'CS', 'CT', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ'
        );

        // 判断标题是否为二维数组
        $header_is_array = false;
        foreach ($header as $key => $value) {
            if(is_array($value)){
                $header_is_array = true;
                break;
            }
        }

        // 生成excel列数
        $column_sum = count($header, 1);
        // 如果是二维数组 减去算进去的一维总数
        if ($header_is_array) {
            $column_sum -= count($header);
        }

        // 是否设置大标题
        if (!$title) {
            $row_start = 1;
        } else {
            $objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', $title);                       // 添加大标题
            $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(24);                 // 设置字体大小
            $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true);               // 设置粗体
            $objPHPExcel->getActiveSheet()->mergeCells('A1:' . $cellName[$column_sum - 1] . '1');   // 合并单元格
            $row_start = 2;
        }

        // 循环输出标题行数据
        if (!$header_is_array) {
            foreach ($header as $key => $value) {
                $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$key] . $row_start, $header[$key]);
                $objPHPExcel->getActiveSheet()->getStyle($cellName[$key] . $row_start)->getFont()->setSize(16);     // 设置字体大小
                $objPHPExcel->getActiveSheet()->getStyle($cellName[$key] . $row_start)->getFont()->setBold(true);   // 设置粗体
                $objPHPExcel->getActiveSheet()->getColumnDimension($cellName[$key])->setWidth($length);                  // 设置宽度
            }
        } else {
            $cells_start = -1;   // 单元格起始位置
            $i = 0;
            foreach ($header as $key => $value) {
                $val_num = count($value); // 统计有多少子数组
                $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$cells_start + 1] . $row_start, $key);
                $objPHPExcel->getActiveSheet()->getStyle($cellName[$cells_start + 1] . $row_start)->getFont()->setSize(20);                                     // 设置字体大小
                $objPHPExcel->getActiveSheet()->getStyle($cellName[$cells_start + 1] . $row_start)->getFont()->setBold(true);                                   // 设置粗体
                $objPHPExcel->getActiveSheet()->mergeCells($cellName[$cells_start + 1] . $row_start . ':' . $cellName[$cells_start + $val_num] . $row_start);   // 合并单元格

                $cells_start += $val_num;

                foreach ($value as $k => $val) {
                    $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$i] . ($row_start + 1), $val);
                    $objPHPExcel->getActiveSheet()->getStyle($cellName[$i] . ($row_start + 1))->getFont()->setSize(16);     // 设置字体大小
                    $objPHPExcel->getActiveSheet()->getColumnDimension($cellName[$i])->setWidth($length);                        // 设置宽度

                    $i ++;
                }
            }

            $row_start += 1;
        }

        // 给表格添加数据
        foreach ($data as $key => $value) {
            // 判断是否为数组
            if (!is_array($value)) {
                die('非二维数组');
            }

            foreach ($value as $k => $v) {
                $row = $key + $row_start + 1;
                // 指定excel表格的显示数据类型 为字符串
                $objPHPExcel->setActiveSheetIndex(0)->setCellValueExplicit($cellName[$k] . $row, $v, \PHPExcel_Cell_DataType::TYPE_STRING);
                $objPHPExcel->getActiveSheet()->getStyle($cellName[$k] . $row)->getFont()->setSize(12);     // 设置字体大小
            }
        }
        // 得到当前活动的表,注意下文教程中会经常用到$objActSheet
        $objActSheet = $objPHPExcel->getActiveSheet();
        // 位置bbb  *为下文代码位置提供锚
        // 给当前活动的表设置名称
        $objActSheet->setTitle('sheet1');

        // 设置单元格边框  锚：bbb
        $style = array(
            'borders' => array(
                'allborders' => array(
                    'style' => \PHPExcel_Style_Border::BORDER_THIN,   // 设置border样式
                    // 'style' => \PHPExcel_Style_Border::BORDER_THICK,  // 另一种样式
                    'color' => array('argb' => 'FF000000'),           // 设置border颜色
                ),
            ),
            'alignment' => array(
                'horizontal' => \PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
            ),
        );


        // 表格总行数
        $table_row = count($data) + $row_start;
        $objActSheet->getStyle('A1:' . $cellName[$column_sum - 1] . $table_row)->applyFromArray($style);

        // $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        // $objWriter->save('myexchel.xlsx');
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"');
        header('Cache-Control: max-age=0');

        $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        $objWriter->save('php://output');
        exit;
    }

    /**
     * 另一种excel导出方式
     * @param $header execl头部中文数组
     * @param $index  头部中文对应数据库字段名数组
     * @param $array  二维数据数组
     * @param $filename  execl文件名
     */
    public static function outputExecl($header, $index, $array, $filename) {
        $time = date('Y-m-d', time());
        //表格头部信息
        $titlename = '';
        $titlename .= "<tr>";
        foreach ($header as $h_key => $h_value) {
            $titlename .= "<th>" . $h_value . "</th>";
        }
        $titlename .= "</tr>";

        $str = "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\nxmlns:x=\"urn:schemas-microsoft-com:office:excel\"\r\nxmlns=\"http://www.w3.org/TR/REC-html40\">\r\n<head>\r\n<meta http-equiv=Content-Type content=\"text/html; charset=utf-8\">\r\n</head>\r\n<body>";

        $str .= "<table border=1><head>" . $titlename . "</head>";
        //表格数据部分
        foreach ($array as $a_key => $a_v) {
            $str .= "<tr>";
            foreach ($index as $i_key => $i_v) {
                $str .= "<td>" . $a_v[$i_v] . "</td>";
            }
            $str .= "</tr>\n";
        }
        $str .= "</table></body></html>";
        echo $str;
        exit;

        header("Content-Type: application/vnd.ms-excel; name='excel'");
        header("Content-type: application/octet-stream");
        header("Content-Disposition: attachment; filename=" . $filename . '_' . $time . '.xls');
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Pragma: no-cache");
        header("Expires: 0");
        return $str;
    }
}
